package com.beemans.common.ext

import android.Manifest
import androidx.annotation.RequiresPermission
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.beemans.common.utils.LocationCallback
import com.beemans.common.utils.LocationConfig
import com.beemans.common.utils.LocationUtils

/**
 * @author ti
 * @date 2022/9/30.
 */
private val locationDelegates by lazy { mutableMapOf<LifecycleOwner, LocationDelegate>() }

@RequiresPermission(
    anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION]
)
fun LifecycleOwner.startLocation(
    config: LocationConfig.() -> Unit = {},
    callback: LocationCallback.() -> Unit = {}
) {
    locationDelegates.getOrPut(this) {
        LocationDelegate(this)
    }.startLocation(config, callback)
}

class LocationDelegate(private val owner: LifecycleOwner) : DefaultLifecycleObserver {
    private var callback: LocationCallback? = null

    init {
        owner.lifecycle.addObserver(this)
    }

    @RequiresPermission(
        anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION]
    )
    fun startLocation(
        config: LocationConfig.() -> Unit = {},
        locationCallback: LocationCallback.() -> Unit = {}
    ) {
        val context = owner.context ?: return
        callback = LocationCallback().apply(locationCallback)
        LocationUtils.startLocation(context, config) {
            onLocationStart {
                callback?.onLocationStart?.invoke()
            }
            onLocationSuccess { location, address ->
                callback?.onLocationSuccess?.invoke(location, address)
            }
            onLocationFailed { error ->
                callback?.onLocationFailed?.invoke(error)
            }
        }
    }

    override fun onDestroy(owner: LifecycleOwner) {
        owner.lifecycle.removeObserver(this)
        locationDelegates.remove(owner)
        callback = null
    }
}